#pragma once

#include "SharedInterfacePtr.h"
#include "WeakObjectPtr.h"

template <typename InterfaceType>
class TWeakInterfacePtr
{
private:
    InterfaceType* Interface=nullptr;
    TWeakObjectPtr<RObject> Object;

public:
    TWeakInterfacePtr()=default;

    TWeakInterfacePtr(std::nullptr_t )
    {
    };

    TWeakInterfacePtr(InterfaceType* InInterface)
    {
        if(InInterface)
        {
            Interface=InInterface;
            Object=InInterface->_GetObjectOfInterface();
        }
    };

    TWeakInterfacePtr(const TSharedInterfacePtr<InterfaceType>& SharedInterface)
    {
        Interface=SharedInterface.Get();
        Object=SharedInterface.GetObject();
    };

    TWeakInterfacePtr(const TWeakInterfacePtr& Other)
    {
        Interface=Other.Interface;
        Object=Other.Object;
    };

    TWeakInterfacePtr& operator=(const TWeakInterfacePtr& Other)
    {
        Interface=Other.Interface;
        Object=Other.Object;
        return *this;
    };

    TWeakInterfacePtr& operator=(InterfaceType* InInterface)
    {
        Interface=InInterface;
        Object=InInterface->_GetObjectOfInterface();
        return *this;
    };

    InterfaceType* Get() const
    {
        return Interface;
    };

    InterfaceType* operator->() const
    {
        return Interface;
    };

    TWeakObjectPtr<RObject> GetObject() const
    {
        return Object;
    };

    bool IsValid() const
    {
        return Object.IsValid();
    };

    operator bool() const
    {
        return Object.IsValid();
    };

    bool operator==(const TWeakInterfacePtr& Other) const
    {
        return Interface == Other.Interface;
    };

    bool operator==(const InterfaceType* OtherInterface) const
    {
        return Interface == OtherInterface;
    };

    bool operator==(std::nullptr_t) const
    {
        return Interface == nullptr;
    };

    bool operator!=(const TWeakInterfacePtr& Other) const
    {
        return Interface != Other.Interface;
    };

    bool operator!=(const InterfaceType* OtherInterface) const
    {
        return Interface != OtherInterface;
    };

    bool operator!=(std::nullptr_t) const
    {
        return Interface != nullptr;
    };

    TSharedInterfacePtr<InterfaceType> Lock() const
    {
        return TSharedInterfacePtr<InterfaceType>(Interface);
    };

};